<script setup>
import { onMounted, ref, watchEffect } from "vue";
import katex from "katex";
import { marked } from "marked";
import "katex/dist/katex.min.css";
import hljs from "highlight.js";
import "highlight.js/styles/vs2015.css";

const props = defineProps({
  content: {
    type: String,
    required: true,
  },
});

const rendered = ref("");

// 配置marked选项
marked.setOptions({
  breaks: true, // 支持Github风格的换行
  gfm: true, // 启用Github风格的Markdown
  highlight: function (code, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(code, { language: lang, ignoreIllegals: true })
          .value;
      } catch (e) {
        console.error("Highlight error:", e);
      }
    }
    return hljs.highlightAuto(code).value;
  },
});

// 创建自定义渲染器
const renderer = new marked.Renderer();
renderer.code = (code, language) => {
  const lines = code
    .split("\n")
    .map(
      (line, index) => `<span class="line-number">${index + 1}</span>${line}`
    )
    .join("\n");

  const langDisplay = language || "plaintext"; // 使用更友好的显示名称
  return `<pre class="hljs-pre" data-language="${langDisplay}"><code class="hljs language-${langDisplay}">${lines}</code></pre>`;
};

watchEffect(() => {
  try {
    // 1. 先处理Markdown
    let processedContent = marked(props.content || "", { renderer });

    // 2. 然后处理LaTeX公式
    processedContent = processedContent.replace(
      /\\\((.*?)\\\)|\\\[(.*?)\\\]/g,
      (match, inline, display) => {
        try {
          return katex.renderToString(inline || display || "", {
            displayMode: !!display,
            throwOnError: false,
          });
        } catch (e) {
          console.error("LaTeX rendering error:", e);
          return match;
        }
      }
    );

    rendered.value = processedContent;
  } catch (e) {
    console.error("Content processing error:", e);
    rendered.value = props.content;
  }
});
</script>

<template>
  <div class="content-renderer" v-html="rendered"></div>
</template>

<style>
.content-renderer {
  line-height: 1.6;
  height: auto;
  min-height: min-content;
  display: inline-block;
  width: 100%;
}

.content-renderer > *:first-child {
  margin-top: 0;
}

.content-renderer > *:last-child {
  margin-bottom: 0;
}

.content-renderer pre.hljs-pre {
  background-color: #1e1e1e;
  padding: 1em;
  border-radius: 4px;
  overflow-x: auto;
  position: relative;
  margin: 1em 0;
  padding-top: 2.5em; /* 为语言标签留出空间 */
}

.content-renderer pre.hljs-pre code {
  font-family: "Fira Code", Consolas, Monaco, "Courier New", monospace;
  font-size: 0.9em;
  counter-reset: line;
}

.content-renderer .line-number {
  display: inline-block;
  width: 2em;
  color: #606366;
  text-align: right;
  margin-right: 1em;
  padding-right: 0.5em;
  border-right: 1px solid #404040;
  user-select: none;
}

.content-renderer code:not(.hljs) {
  font-family: "Fira Code", Consolas, Monaco, "Courier New", monospace;
  font-size: 0.9em;
  padding: 0.2em 0.4em;
  background-color: #2d2d2d;
  border-radius: 3px;
  margin: 0 0.2em;
}

.content-renderer p {
  margin: 1em 0;
}

.content-renderer ul,
.content-renderer ol {
  margin: 1em 0;
  padding-left: 2em;
}

.content-renderer blockquote {
  margin: 1em 0;
  padding-left: 1em;
  border-left: 4px solid #666;
  color: #888;
}

/* 修改语言标识样式 */
.content-renderer pre.hljs-pre::before {
  content: attr(data-language);
  position: absolute;
  top: 0.3em;
  left: 1em;
  color: #888;
  font-size: 0.8em;
  font-family: monospace;
  text-transform: lowercase;
  background-color: #2d2d2d;
  padding: 0.2em 0.5em;
  border-radius: 3px;
  z-index: 1;
}
</style>
